﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Intelligent.OTC.Common.UnitOfWork;
using Intelligent.OTC.Domain.DataModel;
using Intelligent.OTC.Domain.Repositories;
using System.Configuration;
using System.IO;
using Intelligent.OTC.Domain;
using Intelligent.OTC.Common;
using System.Data.Entity.Validation;
using Intelligent.OTC.Common.Attr;
using Intelligent.OTC.Common.Utils;
using Intelligent.OTC.Common.Exceptions;
using System.Data.Entity;
using System.Web;
using Newtonsoft.Json;
using Intelligent.OTC.Business;
using System.Transactions;
using EntityFramework.BulkInsert.Extensions;
using System.Net.Http;
using System.Net;
using System.Net.Http.Headers;

namespace Intelligent.OTC.Business
{
    public class MyinvoicesService
    {
        #region Parameters
        public string CurrentDeal
        {
            get
            {
                return AppContext.Current.User.Deal.ToString();
            }
        }
        public string CurrentUser
        {
            get
            {
                return AppContext.Current.User.EID.ToString();
            }
        }
        public DateTime CurrentTime
        {
            get
            {
                return AppContext.Current.User.Now;
            }
        }
        public int SupervisorPermission
        {
            get
            {
                if (AppContext.Current.User.ActionPermissions.IndexOf("alldataforsupervisor") >= 0)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }

            }
        }

        public OTCRepository CommonRep { get; set; }

        #endregion

        public IEnumerable<MyinvoicesDto> GetMyinvoicesList(string closeType)
        {
            IQueryable<InvoiceAging> tempInvoices = null;
            List<MyinvoicesDto> myinvoices = new List<MyinvoicesDto>();
            MyinvoicesDto myinvoice = new MyinvoicesDto();
            IQueryable<CustomerTeam> tempcusList = null;

            //Current User's customers
            if (SupervisorPermission == 1)
            {
                tempcusList = CommonRep.GetDbSet<CustomerTeam>().Where(o => o.Deal == CurrentDeal);

                //with closeType
                if (closeType == "0")
                {
                    tempInvoices = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && (o.States == "004001" || o.States == "004002" || o.States == "004004" || o.States == "004008" || o.States == "004010" || o.States == "004011" || o.States == "004012"));
                }
                else if (closeType == "1")
                {
                    tempInvoices = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && (o.States == "004003" || o.States == "004005" || o.States == "004006" || o.States == "004007" || o.States == "004009"));
                }
                else
                {
                    tempInvoices = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal);
                }

            }
            else
            {
                tempcusList = CommonRep.GetDbSet<CustomerTeam>().Where(o => o.Deal == CurrentDeal && o.Collector == CurrentUser);

                List<string> cusList = new List<string>();
                cusList = tempcusList.Select(o => o.CustomerNum).ToList<string>();

                //get invoiceList by custListResult
                //with closeType
                if (closeType == "0")
                {
                    tempInvoices = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && cusList.Contains(o.CustomerNum)
                        && (o.States == "004001" || o.States == "004002" || o.States == "004004" || o.States == "004008" || o.States == "004010" || o.States == "004011" || o.States == "004012"));
                }
                else if (closeType == "1")
                {
                    tempInvoices = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && cusList.Contains(o.CustomerNum)
                        && (o.States == "004003" || o.States == "004005" || o.States == "004006" || o.States == "004007" || o.States == "004009"));
                }
                else
                {
                    tempInvoices = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && cusList.Contains(o.CustomerNum));
                }
            }
            var r = from invs in tempInvoices
                    join grp in tempcusList on new {  invs.Deal, invs.CustomerNum } equals new {  grp.Deal, grp.CustomerNum }
                    //into grps
                    //from grp in grps.DefaultIfEmpty()
                    select new MyinvoicesDto
                    {
                        Id = invs.Id,
                        Deal = invs.Deal,
                        LegalEntity = invs.LegalEntity,
                        CustomerNum = invs.CustomerNum,
                        CustomerName = invs.CustomerName,
                        InvoiceNum = invs.InvoiceNum,
                        GroupCodeOld = grp.BillGroupCode,
                        GroupNameOld = grp.BillGroupName,
                        MstCustomer = invs.MstCustomer,
                        PoNum = invs.PoNum,
                        SoNum = invs.SoNum,
                        Class = invs.Class,
                        Currency = invs.Currency,
                        Country = invs.CustomerCountry,
                        //States = !String.IsNullOrEmpty(invs.States) ? Helper.CodeToEnum<InvoiceStatus>(invs.States).ToString().Replace("_", " ") : "",
                        States = invs.States,
                        //dayLate = (AppContext.Current.User.Now.Date - Convert.ToDateTime(invs.DueDate).Date).Days.ToString(),
                        //dayLate,
                        OriginalAmt = invs.OriginalAmt,
                        BalanceAmt = invs.BalanceAmt,
                        CreditTrem = invs.CreditTrem,
                        //TrackStates = !string.IsNullOrEmpty(invs.TrackStates) ? Helper.CodeToEnum<TrackStatus>(invs.TrackStates).ToString().Replace("_", " ") : "",
                        TrackStates = invs.TrackStates,
                        InvoiceDate = invs.InvoiceDate,
                        DueDate = invs.DueDate,
                        CreateDate = invs.CreateDate,
                        UpdateDate = invs.UpdateDate,
                        PtpDate = invs.PtpDate,
                        Remark = invs.Remark,
                        Collector = grp.Collector,
                        CollectorName = grp.CollectorName,
                        TeamName = grp.TeamName,
                        Comments = invs.Comments
                    };
                
            return r;
        }

        public HttpResponseMessage ExportInvoicesList(string custCode,string custName,string billCode,string billName,
                                                      string invNum,string poNum,string soNum,string rbo,string creTerm,
                                                      string close, string legal, string doc, string state, string tstate,
                                                      string memo, string oper, string pdf, string pdt, string idf, string idt, string ddf, string ddt)
        {
            List<Customer.ExpCustomerDto> lstCustomer = new List<Customer.ExpCustomerDto>();
            List<InvoiceAging> invoiceList = new List<InvoiceAging>();
            InvoiceAging invoice = new InvoiceAging();
            string templateFile = "";
            string fileName = "";
            string tmpFile = "";

            try
            {
                //模板文件  
                templateFile = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["ExportInvoiceTemplate"].ToString());
                fileName = AppContext.Current.User.EID + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".xlsx";
                tmpFile = Path.Combine(Path.GetTempPath(), fileName);

                //invoice list
                IQueryable<InvoiceAging> tempInvoicesOld = null;
                IQueryable<CustomerTeam> tempcusList = null;

                //Current User's customers
                if (SupervisorPermission == 1)
                {
                    tempcusList = CommonRep.GetDbSet<CustomerTeam>().Where(o => o.Deal == CurrentDeal);

                    if (string.IsNullOrEmpty(close) || close == "0" || close == "undefined")
                    {
                        tempInvoicesOld = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && (o.States == "004001" || o.States == "004002" || o.States == "004004" || o.States == "004008" || o.States == "004010" || o.States == "004011" || o.States == "004012"));
                    }
                    else if (close == "1")
                    {
                        tempInvoicesOld = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && (o.States == "004003" || o.States == "004005" || o.States == "004006" || o.States == "004007" || o.States == "004009"));
                    }
                    else
                    {
                        tempInvoicesOld = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal);
                    }

                }
                else
                {
                    tempcusList = CommonRep.GetDbSet<CustomerTeam>().Where(o => o.Deal == CurrentDeal && o.Collector == CurrentUser);
                    List<string> cusList = new List<string>();
                    cusList = tempcusList.Select(o => o.CustomerNum).ToList<string>();

                    //with closeType
                    if (string.IsNullOrEmpty(close) || close == "0" || close == "undefined")
                    {
                        tempInvoicesOld = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && cusList.Contains(o.CustomerNum)
                            && (o.States == "004001" || o.States == "004002" || o.States == "004004" || o.States == "004008" || o.States == "004010" || o.States == "004011" || o.States == "004012"));
                    }
                    else if (close == "1")
                    {
                        tempInvoicesOld = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && cusList.Contains(o.CustomerNum)
                            && (o.States == "004003" || o.States == "004005" || o.States == "004006" || o.States == "004007" || o.States == "004009"));
                    }
                    else
                    {
                        tempInvoicesOld = CommonRep.GetDbSet<InvoiceAging>().Where(o => o.Deal == CurrentDeal && cusList.Contains(o.CustomerNum));
                    }
                }

                var tempInvoices = from invs in tempInvoicesOld
                                   join grp in tempcusList on new {  invs.Deal, invs.CustomerNum } equals new { grp.Deal, grp.CustomerNum }
                                   select new MyinvoicesDto
                                   {
                                       Id = invs.Id,
                                       Deal = invs.Deal,
                                       LegalEntity = invs.LegalEntity,
                                       CustomerNum = invs.CustomerNum,
                                       CustomerName = invs.CustomerName,
                                       InvoiceNum = invs.InvoiceNum,
                                       GroupCodeOld = grp.BillGroupCode,
                                       GroupNameOld = grp.BillGroupName,
                                       MstCustomer = invs.MstCustomer,
                                       PoNum = invs.PoNum,
                                       SoNum = invs.SoNum,
                                       Class = invs.Class,
                                       Currency = invs.Currency,
                                       Country = invs.CustomerCountry,
                                       //States = !String.IsNullOrEmpty(invs.States) ? Helper.CodeToEnum<InvoiceStatus>(invs.States).ToString().Replace("_", " ") : "",
                                       States = invs.States,
                                       //dayLate = (AppContext.Current.User.Now.Date - Convert.ToDateTime(invs.DueDate).Date).Days.ToString(),
                                       //dayLate,
                                       OriginalAmt = invs.OriginalAmt,
                                       BalanceAmt = invs.BalanceAmt,
                                       CreditTrem = invs.CreditTrem,
                                       //TrackStates = !string.IsNullOrEmpty(invs.TrackStates) ? Helper.CodeToEnum<TrackStatus>(invs.TrackStates).ToString().Replace("_", " ") : "",
                                       TrackStates = invs.TrackStates,
                                       InvoiceDate = invs.InvoiceDate,
                                       DueDate = invs.DueDate,
                                       CreateDate = invs.CreateDate,
                                       UpdateDate = invs.UpdateDate,
                                       PtpDate = invs.PtpDate,
                                       Remark = invs.Remark,
                                       Collector = grp.Collector,
                                       CollectorName = grp.CollectorName,
                                       TeamName = grp.TeamName,
                                       Comments = invs.Comments
                                   };

                if (!string.IsNullOrEmpty(custCode) && custCode != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.CustomerNum.IndexOf(custCode) >= 0);
                }
                if (!string.IsNullOrEmpty(custName) && custName != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.CustomerName.IndexOf(custName) >= 0);
                }
                if (!string.IsNullOrEmpty(billCode) && billCode != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.GroupCodeOld.IndexOf(billCode) >= 0);
                }
                if (!string.IsNullOrEmpty(billName) && billName != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.GroupNameOld.IndexOf(billName) >= 0);
                }
                if (!string.IsNullOrEmpty(invNum) && invNum != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.InvoiceNum.IndexOf(invNum) >= 0);
                }
                if (!string.IsNullOrEmpty(poNum) && poNum != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.PoNum.IndexOf(poNum) >= 0);
                }
                if (!string.IsNullOrEmpty(soNum) && soNum != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.SoNum.IndexOf(soNum) >= 0);
                }
                if (!string.IsNullOrEmpty(rbo) && rbo != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.MstCustomer.IndexOf(rbo) >= 0);
                }
                if (!string.IsNullOrEmpty(creTerm) && creTerm != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.CreditTrem.IndexOf(creTerm) >= 0);
                }

                if (!string.IsNullOrEmpty(legal) && legal != "null" && legal != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.LegalEntity == legal);
                }
                if (!string.IsNullOrEmpty(doc) && doc != "null" && doc != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.Class == doc);
                }
                if (!string.IsNullOrEmpty(state) && state != "null" && state != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.States == state);
                }
                if (!string.IsNullOrEmpty(tstate) && tstate != "null" && tstate != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.TrackStates == tstate);
                }

                if (!string.IsNullOrEmpty(memo) && memo != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.Comments.IndexOf(memo) >= 0);
                }
                if (!string.IsNullOrEmpty(oper) && oper != "null" && oper != "undefined")
                {
                    tempInvoices = tempInvoices.Where(o => o.Collector == oper);
                }
                if (!string.IsNullOrEmpty(pdf) && pdf != "undefined" && pdf !="null")
                {
                    DateTime pdfDate = Convert.ToDateTime(pdf + " 00:00:00");
                    tempInvoices = tempInvoices.Where(o => o.PtpDate >= pdfDate);
                }
                if (!string.IsNullOrEmpty(pdt) && pdt != "undefined" && pdt != "null")
                {
                    DateTime pdtDate = Convert.ToDateTime(pdt + " 23:59:59");
                    tempInvoices = tempInvoices.Where(o => o.PtpDate <= pdtDate);
                }
                if (!string.IsNullOrEmpty(idf) && idf != "undefined" && idf != "null")
                {
                    DateTime idfDate = Convert.ToDateTime(idf + " 00:00:00");
                    tempInvoices = tempInvoices.Where(o => o.InvoiceDate >= idfDate);
                }
                if (!string.IsNullOrEmpty(idt) && idt != "undefined" && idt != "null")
                {
                    DateTime idtDate = Convert.ToDateTime(idt + " 23:59:59");
                    tempInvoices = tempInvoices.Where(o => o.InvoiceDate <= idtDate);
                } if (!string.IsNullOrEmpty(ddf) && ddf != "undefined" && ddf != "null")
                {
                    DateTime ddfDate = Convert.ToDateTime(ddf + " 00:00:00");
                    tempInvoices = tempInvoices.Where(o => o.DueDate >= ddfDate);
                }
                if (!string.IsNullOrEmpty(ddt) && ddt != "undefined" && ddt != "null")
                {
                    DateTime ddtDate = Convert.ToDateTime(ddt + " 23:59:59");
                    tempInvoices = tempInvoices.Where(o => o.DueDate <= ddtDate);
                }

                this.setData(templateFile, tmpFile, tempInvoices);

                HttpResponseMessage response = new HttpResponseMessage();
                response.StatusCode = HttpStatusCode.OK;
                MemoryStream fileStream = new MemoryStream();
                if (File.Exists(tmpFile))
                {
                    using (FileStream fs = File.OpenRead(tmpFile))
                    {
                        fs.CopyTo(fileStream);
                    }
                }
                else
                {
                    throw new OTCServiceException("Get file failed because file not exist with physical path: " + tmpFile);
                }
                Stream ms = fileStream;
                ms.Position = 0;
                response.Content = new StreamContent(ms);
                response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                {
                    FileName = fileName
                };
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                response.Content.Headers.ContentLength = ms.Length;

                return response;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                //File.Delete(tmpFile);
            }
        }

        #region Set Invoice Report Datas
        private void setData(string templateFileName, string tmpFile, IQueryable<MyinvoicesDto> lstDatas)
        {
            int rowNo = 1;

            try
            {
                NpoiHelper helper = new NpoiHelper(templateFileName);
                helper.Save(tmpFile, true);
                helper = new NpoiHelper(tmpFile);
                string sheetName = "";

                foreach (string sheet in helper.Sheets)
                {
                    sheetName = sheet;
                    break;
                }

                //设置sheet
                helper.ActiveSheetName = sheetName;

                //设置Excel的内容信息
                foreach (var lst in lstDatas)
                {
                    helper.SetData(rowNo, 0, lst.CustomerNum);
                    helper.SetData(rowNo, 1, lst.CustomerName);
                    helper.SetData(rowNo, 2, lst.LegalEntity);
                    helper.SetData(rowNo, 3, lst.InvoiceNum);
                    helper.SetData(rowNo, 4, string.IsNullOrEmpty(lst.InvoiceDate.ToString()) ? "" : lst.InvoiceDate.Value.ToString("yyyy-MM-dd"));
                    helper.SetData(rowNo, 5, lst.CreditTrem);
                    helper.SetData(rowNo, 6, string.IsNullOrEmpty(lst.DueDate.ToString()) ? "" : lst.DueDate.Value.ToString("yyyy-MM-dd"));
                    helper.SetData(rowNo, 7, lst.PoNum);
                    helper.SetData(rowNo, 8, lst.SoNum);
                    helper.SetData(rowNo, 9, lst.Country);
                    helper.SetData(rowNo, 10, lst.TeamName);
                    helper.SetData(rowNo, 11, lst.Collector);
                    helper.SetData(rowNo, 12, lst.MstCustomer);
                    helper.SetData(rowNo, 13, lst.Currency);
                    helper.SetData(rowNo, 14, lst.OriginalAmt);
                    helper.SetData(rowNo, 15, lst.BalanceAmt);
                    helper.SetData(rowNo, 16, lst.dayLate);
                    helper.SetData(rowNo, 17, !String.IsNullOrEmpty(lst.TrackStates) ? Helper.CodeToEnum<TrackStatus>(lst.TrackStates).ToString().Replace("_", " ") : "");
                    helper.SetData(rowNo, 18, !String.IsNullOrEmpty(lst.States) ? Helper.CodeToEnum<InvoiceStatus>(lst.States).ToString().Replace("_", " ") : "");
                    helper.SetData(rowNo, 19, string.IsNullOrEmpty(lst.PtpDate.ToString()) ? "" : lst.PtpDate.Value.ToString("yyyy-MM-dd"));
                    helper.SetData(rowNo, 20, lst.Class);
                    helper.SetData(rowNo, 21, lst.Comments);

                    rowNo++;
                }

                //formula calcuate result
                helper.Save(tmpFile, true);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion
    }
}
